package org.odst.transformer;

import java.util.Calendar;
import java.util.Currency;
import java.util.Date;
import java.util.Locale;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.odftoolkit.odfdom.OdfFileDom;
import org.odftoolkit.odfdom.doc.number.OdfNumberCurrencyStyle;
import org.odftoolkit.odfdom.doc.office.OdfOfficeStyles;
import org.odst.formula.Formula;
import org.odst.parser.Cell;
import org.odst.parser.Expression;

/**
 * Cell transformation class
 * 
 * @author Leonid Vysochyn
 * @author Cyril PODER
 */
public class CellTransformer {
	protected final Log log = LogFactory.getLog(getClass());

	private Configuration configuration;

	public CellTransformer(Configuration configuration) {
		if (configuration != null) {
			this.configuration = configuration;
		} else {
			this.configuration = new Configuration();
		}
	}

	void transform(int rowIndex, Cell cell) {
		try {
			if (cell.getOooCell() != null /*
										 * &&
										 * cell.getOooCell().getType().equals(
										 * CellContentType.TEXT)
										 */) {
				if (cell.getCollectionProperty() == null) {
					// if (cell.getFormula() == null) {
					if (cell.getExpressions().size() == 0) {
						if (cell.getMetaInfo() != null) {
							cell.getOooCell().setStringValue(
									cell.getStringCellValue());
						}
					} else if (cell.getExpressions().size() == 1) {
						Object value = ((Expression) cell.getExpressions().get(
								0)).evaluate();
						if (value == null) {
							cell.getOooCell().setStringValue("");
						} else {
							if (cell.getOooCell().getOdfElement().getAutomaticStyle() != null && cell.getOooCell().getOdfElement().getAutomaticStyle().getStyleDataStyleNameAttribute() != null) {
								String dataStyleName = cell.getOooCell().getOdfElement().getAutomaticStyle().getStyleDataStyleNameAttribute();
								OdfOfficeStyles styles = ((OdfFileDom)cell.getOooCell().getOdfElement().getOwnerDocument()).getOdfDocument().getDocumentStyles();
								if (styles.getPercentageStyle(dataStyleName) != null && value instanceof Number) {
									cell.getOooCell().setPercentageValue(((Number)value).doubleValue());
								} else if (styles.getNumberStyle(dataStyleName) != null && value instanceof Number) {
									cell.getOooCell().setDoubleValue(((Number)value).doubleValue());
								} else if (styles.getDateStyle(dataStyleName) != null && (value instanceof Date || value instanceof Calendar)) {
									if (value instanceof Date) {
			                        	Calendar cal = Calendar.getInstance();
			                        	cal.setTime((Date)value);
			                        	cell.getOooCell().setDateValue(cal);
			                        }else if (value instanceof Calendar) {
			                        	cell.getOooCell().setDateValue((Calendar) value);
			                        }
								} else if (styles.getBooleanStyle(dataStyleName) != null && value instanceof Boolean) {
									cell.getOooCell().setBooleanValue((Boolean)value);
								} else if (styles.getCurrencyStyle(dataStyleName) != null && value instanceof Number) {
									OdfNumberCurrencyStyle currencyStyle = styles.getCurrencyStyle(dataStyleName);
									String currencySymbol = "";
									if (currencyStyle.getCurrencySymbolElement() != null)
										currencySymbol = styles.getCurrencyStyle(dataStyleName).getCurrencySymbolElement().getTextContent();
									else {
										String countryCode = currencyStyle.getNumberCountryAttribute();
										String languageCode = currencyStyle.getNumberLanguageAttribute();
										if (countryCode != null && languageCode != null)
											currencySymbol = Currency.getInstance(new Locale(languageCode, countryCode)).getCurrencyCode();
									}
									cell.getOooCell().setCurrencyValue(((Number)value).doubleValue(), currencySymbol);
								} else if (value instanceof Number) {
									cell.getOooCell().setDoubleValue(((Number)value).doubleValue());
								} else if (value instanceof Date) {
		                        	Calendar cal = Calendar.getInstance();
		                        	cal.setTime((Date)value);
		                        	cell.getOooCell().setDateValue(cal);
		                        } else if (value instanceof Calendar) {
		                        	cell.getOooCell().setDateValue((Calendar) value);
		                        } else if (value instanceof Boolean) {
		                        	cell.getOooCell().setBooleanValue((Boolean) value);
		                        } else
									cell.getOooCell().setStringValue(value.toString());
							} else {
								if (value instanceof Number) {
									cell.getOooCell().setDoubleValue(((Number)value).doubleValue());
		                        } else if (value instanceof Date) {
		                        	Calendar cal = Calendar.getInstance();
		                        	cal.setTime((Date)value);
		                        	cell.getOooCell().setDateValue(cal);
		                        } else if (value instanceof Calendar) {
		                        	cell.getOooCell().setDateValue((Calendar) value);
		                        } else if (value instanceof Boolean) {
		                        	cell.getOooCell().setBooleanValue((Boolean) value);
	    						} else
	    							cell.getOooCell().setStringValue(value.toString());
							}
						}
					} else {
						if (cell.getExpressions().size() > 1) {
							String value = "";
							for (int i = 0; i < cell.getExpressions().size(); i++) {
								Expression expr = (Expression) cell
										.getExpressions().get(i);
								Object propValue = expr.evaluate();
								if (propValue != null) {
									value += propValue.toString();
								}
							}
							// setCellValue(cell, value);
							cell.getOooCell().setStringValue(value);
						}
					}
					/*
					 * } else if (cell.getFormula() != null) {
					 * processFormulaCell( cell ); }
					 */
				} else {
					String value = "";
					for (int i = 0; i < cell.getExpressions().size(); i++) {
						Expression expr = (Expression) cell.getExpressions()
								.get(i);
						if (expr.getCollectionProperty() == null) {
							value += expr.evaluate();
						} else {
							value += configuration.getStartExpressionToken()
									+ expr.getExpression()
									+ configuration.getEndExpressionToken();
						}
					}
					// setCellValue(cell, value);
					cell.getOooCell().setStringValue(value);
				}
				if (cell.getFormula() != null) {
					if (cell.getExpressions().size() > 1) {
						String value = "";
						for (int i = 0; i < cell.getExpressions().size(); i++) {
							Expression expr = (Expression) cell
									.getExpressions().get(i);
							value += expr.evaluate();
						}
						cell.setFormula(new Formula(value.substring(2, value
								.lastIndexOf(']'))));
						// setCellValue(cell, value);
						cell.getOooCell().setStringValue(value);
					}
					processFormulaCell(rowIndex, cell);
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
			log.debug("Can't parse expression");
		}
	}

	private static void processFormulaCell(int rowIndex, Cell cell) {
		// processing formula
		Formula formula = cell.getFormula();
		if (formula.isInline()) {
			if (cell.getCollectionName() != null) {
				// simple copy of inline formula template
				// it will be processed when individual rows are processed
				cell.getOooCell().setStringValue(cell.getStringCellValue());
			} else {
				// processing of inline formulaString template
				String formulaString = formula.getInlineFormula(cell.getRow()
						.getOooRow().getRowIndex() + 1, getColName(cell.getOooCell().getColumnIndex()));
				cell.getOooCell().setFormula("=" + formulaString);
			}
		}
	}
	
    
    private static String getColName(int col) {
    	String result = "";
    	
    	if (col > 25)
    		result += getColName(col / 26);
    	
    	result += (char)('A' + (char)(col%26));
    	
    	return result;
    }

}
